import {Cell, CellView, Graph, Node} from '@antv/x6';
import {Snapline} from '@antv/x6-plugin-snapline';
import BuildingSVG from '@/assets/f2.svg';
import {Dnd} from '@antv/x6-plugin-dnd';
import {MiniMap} from '@antv/x6-plugin-minimap';
import {Selection} from '@antv/x6-plugin-selection';
import {Keyboard} from '@antv/x6-plugin-keyboard';
import {Clipboard} from '@antv/x6-plugin-clipboard';
import {History} from '@antv/x6-plugin-history';
import GraphStore from '@/store/graph';
import {isEmpty} from 'lodash';
import {isMac} from '@/utils/variable';

Graph.registerNode('top-left-seat', {
    inherit: 'rect', // 继承于 rect 节点
    // width: 100,
    // height: 100,
    markup: {
        tagName: 'path',
        selector: 'body',
        attrs: {
            d: 'M23 23H0V17H6L5.9989 16.9505C6.21841 16.9723 6.44001 16.9871 6.66346 16.9944L7 17L7.27991 16.9962C12.6733 16.8479 17 12.4292 17 7C17 6.66226 16.9833 6.32843 16.9506 5.99929L17 6V0L23 0V23ZM13 8.5C13 10.9853 10.9853 13 8.5 13C6.01472 13 4 10.9853 4 8.5C4 6.01472 6.01472 4 8.5 4C10.9853 4 13 6.01472 13 8.5Z'
        }
    },
    data: {}
});

Graph.registerNode('bottom-left-seat', {
    inherit: 'rect', // 继承于 rect 节点
    width: 10,
    height: 10,
    markup: {
        tagName: 'path',
        selector: 'body',
        attrs: {
            d: 'M23 0H0V6H6L5.9989 6.04948C6.21841 6.02767 6.44001 6.01295 6.66346 6.00556L7 6L7.2799 6.00384C12.6733 6.15207 17 10.5708 17 16C17 16.3377 16.9833 16.6716 16.9506 17.0007L17 17V23H23V0ZM13 14.5C13 12.0147 10.9853 10 8.5 10C6.01472 10 4 12.0147 4 14.5C4 16.9853 6.01472 19 8.5 19C10.9853 19 13 16.9853 13 14.5Z'
        }
    },
    data: {}
});

Graph.registerNode('top-right-seat', {
    inherit: 'rect', // 继承于 rect 节点
    width: 10,
    height: 10,
    markup: {
        tagName: 'path',
        selector: 'body',
        attrs: {
            d: 'M0 23H23V17H17L17.0011 16.9505C16.7816 16.9723 16.56 16.9871 16.3365 16.9944L16 17L15.7201 16.9962C10.3267 16.8479 6 12.4292 6 7C6 6.66226 6.01674 6.32843 6.04945 5.99929L6 6V0L0 0L0 23ZM10 8.5C10 10.9853 12.0147 13 14.5 13C16.9853 13 19 10.9853 19 8.5C19 6.01472 16.9853 4 14.5 4C12.0147 4 10 6.01472 10 8.5Z'
        }
    },
    attrs: {
        body: {
            fill: '#808080'
        }
    },
    data: {}
});

Graph.registerNode('bottom-right-seat', {
    inherit: 'rect', // 继承于 rect 节点
    width: 10,
    height: 10,
    markup: {
        tagName: 'path',
        selector: 'body',
        attrs: {
            d: 'M0 0H23V6H17L17.0011 6.04948C16.7816 6.02767 16.56 6.01295 16.3365 6.00556L16 6L15.7201 6.00384C10.3267 6.15207 6 10.5708 6 16C6 16.3377 6.01674 16.6716 6.04945 17.0007L6 17V23H0L0 0ZM10 14.5C10 12.0147 12.0147 10 14.5 10C16.9853 10 19 12.0147 19 14.5C19 16.9853 16.9853 19 14.5 19C12.0147 19 10 16.9853 10 14.5Z'
        }
    },
    attrs: {
        body: {
            fill: '#808080'
        }
    },
    data: {}
});

Graph.registerNode('group-square', {
    inherit: 'rect', // 继承于 rect 节点
    width: 40,
    height: 40,
    attrs: {
        style: {
            pointerEvents: 'none'
        },
        body: {
            border: 'none'
        }
    }
});

class Dragger {
    graph: Graph | null;
    dnd: Dnd | null;
    graphStore: typeof GraphStore | null;
    constructor() {
        this.graph = null;
        this.dnd = null;
        this.graphStore = null;
    }

    initGraph(graphStore: typeof GraphStore) {
        this.graphStore = graphStore;
        const container = document.getElementById('container');
        if (!container) {
            return;
        }
        const graph = new Graph({
            container,
            grid: {
                size: 1, // 网格大小 10px
                visible: true // 绘制网格，默认绘制 dot 类型网格
            },
            width: container.clientWidth,
            height: container.clientHeight,
            panning: {
                enabled: true,
                modifiers: ['ctrl', 'meta'],
                eventTypes: ['leftMouseDown']
            },
            scaling: {
                min: 0.1, // 默认值为 0.01
                max: 10 // 默认值为 16
            },
            mousewheel: {
                enabled: true,
                modifiers: ['ctrl', 'meta']
            },
            interacting: {
                nodeMovable: (cellView: CellView) => {
                    // 判断是空的
                    if (cellView.cell.data && cellView.cell.data.type === 'floor-image') {
                        return false;
                    }
                    return true;
                }
            }
        });
        this.graph = graph;
        this.useGraphPlugin(container);
        this.bindMouseEvents();
        this.bindKeyEvents();

        graph.addNode({
            shape: 'image',
            width: 1200,
            height: 800,
            imageUrl: BuildingSVG,
            // markup: [],
            attrs: {
                style: {
                    pointerEvents: 'none'
                },
                body: {
                    stroke: '#000', // 边框颜色
                    style: {
                        pointerEvents: 'none'
                    }
                }
            },
            data: {
                type: 'floor-image'
            }
        });

        // 过滤框选节点
        graph.setSelectionFilter((cell: Cell) => {
            if (cell.data && cell.data.type === 'floor-image') {
                return false;
            }
            return true;
        });

        graph.on('node:added', () => {
            this.saveData();
        });

        graph.on('node:added', ({node}) => {
            const {x, y} = node.position();
            const shape = node.shape;
            if (shape === 'group-square') {
                const node1 = this.createNode('top-left-seat');
                const node2 = this.createNode('bottom-left-seat');
                const node3 = this.createNode('top-right-seat');
                const node4 = this.createNode('bottom-right-seat');

                if (node1) {
                    node1.setPosition({
                        x,
                        y
                    });
                    this.graph?.addCell(node1);
                }
                if (node2) {
                    node2.setPosition({
                        x,
                        y: y + node2.getSize().height
                    });
                    this.graph?.addCell(node2);
                }
                if (node3) {
                    node3.setPosition({
                        x: x + node3.getSize().width,
                        y
                    });
                    this.graph?.addCell(node3);
                }
                if (node4) {
                    node4.setPosition({
                        x: x + node4.getSize().width,
                        y: y + node4.getSize().height
                    });
                    this.graph?.addCell(node4);
                }
                this.graph?.removeCell(node);
            }
        });

        this.graph.centerContent();
    }

    useGraphPlugin(container: HTMLElement) {
        if (!this.graph) {
            return false;
        }
        // 添加辅助线
        this.graph.use(
            new Snapline({
                enabled: true
            })
        );

        // 添加小地图
        this.graph.use(
            new MiniMap({
                container,
                width: 200,
                height: 200
            })
        );

        // 添加框选
        this.graph.use(
            new Selection({
                enabled: true,
                multiple: true,
                rubberband: true,
                selectCellOnMoved: true,
                movable: true,
                showNodeSelectionBox: true
            })
        );

        // 开启键盘支持
        this.graph.use(
            new Keyboard({
                enabled: true
            })
        );

        // 加入复制粘贴功能
        this.graph.use(
            new Clipboard({
                enabled: true
            })
        );

        // undo功能
        this.graph.use(
            new History({
                enabled: true
            })
        );
    }

    bindMouseEvents() {
        if (!this.graph) {
            return;
        }
        // 触发点击事件
        this.graph.on('cell:dblclick', ({node}: {node: Node}) => {
            const data = node.getData();
            if (!isEmpty(data)) {
                this.graphStore?.setWorkStationProps(data);
            } else {
                this.graphStore?.resetWorkStationProps();
            }
            this.graphStore?.setCurNodeId(node.id);
            this.graphStore?.setEditDialogVisible(true);
        });

        // 光标点击事件
        this.graph.on('blank:mouseup', () => {
            this.graphStore?.setEditDialogVisible(false);
            this.graphStore?.resetWorkStationProps();
        });

        this.graph.on('cell:mouseup', () => {
            this.saveData();
        });
    }

    // 绑定键盘事件
    bindKeyEvents() {
        if (!this.graph) {
            return;
        }
        // 快捷删除按键
        this.graph.bindKey(['Backspace', 'Delete'], () => {
            const cells = this.graph?.getSelectedCells();
            if (cells?.length) {
                this.graph?.removeCells(cells);
                this.saveData();
            }
        });

        // 复制
        this.graph.bindKey(isMac() ? 'command+c' : 'ctrl+c', () => {
            const cells = this.graph?.getSelectedCells();
            if (cells?.length) {
                this.graph?.copy(cells);
            }
            return false;
        });

        // 粘贴
        this.graph.bindKey(isMac() ? 'command+v' : 'ctrl+v', () => {
            if (!this.graph?.isClipboardEmpty()) {
                const cells = this.graph?.paste({offset: 20});
                this.graph?.cleanSelection();
                this.graph?.select(cells!);
            }
            return false;
        });

        // 撤销
        this.graph.bindKey(isMac() ? 'command+z' : 'ctrl+z', () => {
            this.graph?.undo();
            return false;
        });

        // 移动 向上
        this.graph.bindKey(['up', 'right', 'down', 'left'], (e: KeyboardEvent) => {
            if (!this.graph) {
                return false;
            }
            const key = e.key;
            const cells = this.graph.getSelectedCells();
            const zoom = this.graph.zoom();
            if (cells?.length) {
                cells.forEach((cell) => {
                    if (this.graph?.isNode(cell)) {
                        const {x, y} = cell.position();
                        if (key === 'ArrowUp') {
                            cell.setPosition({
                                x,
                                y: y - zoom
                            });
                        }
                        if (key === 'ArrowRight') {
                            cell.setPosition({
                                x: x + zoom,
                                y: y
                            });
                        }
                        if (key === 'ArrowDown') {
                            cell.setPosition({
                                x,
                                y: y + zoom
                            });
                        }
                        if (key === 'ArrowLeft') {
                            cell.setPosition({
                                x: x - zoom,
                                y
                            });
                        }
                    }
                });
                this.saveData();
            }

            return false;
        });
    }

    initDnd() {
        if (!this.graph) {
            return false;
        }
        this.dnd = new Dnd({
            target: this.graph
        });
    }

    startDrag(shapeName: string, e: React.MouseEvent<HTMLDivElement, MouseEvent>) {
        if (!this.graph || !this.dnd) {
            return false;
        }

        // const zoom = this.graph.zoom();
        const node = this.graph.createNode({
            shape: shapeName,
            width: 23 * 0.5,
            height: 23 * 0.5,
            attrs: {
                body: {
                    fill: '#808080',
                    style: {
                        transform: `scale(${0.5})`
                    }
                }
            }
        });
        this.dnd.start(node, e.nativeEvent);
    }

    createNode(shapeName: string) {
        return this.graph?.createNode({
            shape: shapeName,
            width: 23 * 0.5,
            height: 23 * 0.5,
            attrs: {
                body: {
                    fill: '#808080',
                    style: {
                        transform: `scale(${0.5})`
                    }
                }
            }
        });
    }

    startGroupDrag(shapeName: string, e: React.MouseEvent<HTMLDivElement, MouseEvent>) {
        if (!this.graph || !this.dnd) {
            return false;
        }

        const parent = this.graph.createNode({
            shape: shapeName,
            width: 23 * 0.5 * 2,
            height: 23 * 0.5 * 2,
            attrs: {
                body: {
                    stroke: 0,
                    style: {
                        pointerEvents: 'none',
                        fill: 'none',
                        transform: `scale(${0.5 * 2})`
                    }
                }
            }
        });
        this.dnd?.start(parent, e.nativeEvent);
    }

    replaceNodeData() {
        if (this.graphStore) {
            const id = this.graphStore.curNodeId;
            const cell = this.graph?.getCellById(id);
            const {status} = this.graphStore.workStationProps;
            let fillColor = '#808080';
            if (status === 1) {
                fillColor = '#808080';
            } else {
                fillColor = '#F44335';
            }
            cell?.setAttrs({
                body: {
                    fill: fillColor
                }
            });
            cell?.replaceData(this.graphStore.workStationProps);

            this.saveData();
        }
    }

    saveData() {
        const cells = this.graph?.toJSON();
        localStorage.setItem('CELL_DATA', JSON.stringify(cells));
    }

    restoreData() {
        const cell = localStorage.getItem('CELL_DATA');
        if (cell) {
            this.graph?.fromJSON(JSON.parse(cell));
        }
    }
}

export default new Dragger();
